﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using lumo.display.object2D;
using lumo.display.animation2D;

namespace lumo.display.gui
{
    /// <summary>
    /// Simple base class for horizontal and vertical command list.
    /// </summary>
    public abstract class PositionableCommandListBase : CommandListBase
    {
        /// <summary>Change Time Each Item.</summary>
        public float ChangeTime      = 500.0f;
        /// <summary>Selected color item.</summary>
        public Color SelectedColor   = new Color(1f, 1f, 1f, 1f);
        /// <summary>Unselected color Item.</summary>
        public Color UnselectedColor = new Color(0.25f, 0.25f, 0.25f, 0.25f);

        /// <summary>
        /// Get the item offset.
        /// </summary>
        protected abstract Vector2 GetItemOffset(int Index);

        /// <summary>
        /// Check the item added.
        /// </summary>
        protected override void CheckItemAdded(object Item)
        {
            if (!(Item is IObject2D))
                throw new Exception("Item in menu is not a IObject2D");
            if (!(Item is IPositionable2D))
                throw new Exception("Item is not valid");
            if (!(Item is IOriginable2D))
                throw new Exception("Item is not valid");
            if (!(Item is IScalable2D))
                throw new Exception("Item is not valid");
            if (!(Item is IColorable))
                throw new Exception("Item is not valid");
        }

        /// <summary>
        /// Get boundaries of an item
        /// </summary>
        protected override Rectangle? GetBoundaries(int Index)
        {
            Vector2 Offset = GetItemOffset(Index);
            float CurrentX = this.X + Offset.X;
            float CurrentY = this.Y + Offset.Y;
            IOriginable2D obj = CommandList[Index] as IOriginable2D;
            return new Rectangle((int)(CurrentX - obj.Size.X / 2), (int)(CurrentY - obj.Size.Y / 2), (int)obj.Size.X, (int)obj.Size.Y);
        }

        /// <summary>
        /// Initialize the item.
        /// </summary>
        protected override void OnInitialize(float Time)
        {
            int i = 0;
            foreach (IPositionable2D obj in CommandList.Cast<IPositionable2D>())
            {
                Vector2 Offset = GetItemOffset(i);
                float CurrentX = this.X + Offset.X;
                float CurrentY = this.Y + Offset.Y;

                obj.Position = this.Position + GetItemOffset(i);
                ++i;
            }
            foreach (IOriginable2D obj in CommandList.Cast<IOriginable2D>())
            {
                obj.Origin = Vector2.Multiply(obj.Size, 0.5f);
            }

            i = 0;
            foreach (IColorable obj in CommandList.Cast<IColorable>())
            {
                obj.Color = new Color(0, 0, 0, 0);

                if (this.Active && (i == this.Index))
                    ParallelAnimation.Add(new ColorAnimation2D(SelectedColor, Time, Smooth.Arrival, Loop.None, obj));
                else
                    ParallelAnimation.Add(new ColorAnimation2D(UnselectedColor, Time, Smooth.Arrival, Loop.None, obj));

                ++i;
            }

        }

        /// <summary>
        /// Setup the item after initialize.
        /// </summary>
        protected override void OnSetup()
        {
        }

        /// <summary>
        /// Terminate the menu.
        /// </summary>
        protected override void OnTerminate(float Time)
        {
        }

        /// <summary>
        /// Unselect the item.
        /// </summary>
        protected override void OnUnselectItem(int ItemIndex, object Item)
        {
            ChangeAnimationDictionary[Item].Clear();
            ChangeAnimationDictionary[Item].Add(new ColorAnimation2D(UnselectedColor, ChangeTime, Smooth.Arrival, Loop.None));
        }

        /// <summary>
        /// Select the item.
        /// </summary>
        protected override void OnSelectItem(int ItemIndex, object Item)
        {
            ChangeAnimationDictionary[Item].Clear();
            ChangeAnimationDictionary[Item].Add(new ColorAnimation2D(SelectedColor, ChangeTime, Smooth.Arrival, Loop.None));
        }

        /// <summary>
        /// Update the item.
        /// </summary>
        protected override void OnDraw(object Item, Microsoft.Xna.Framework.Graphics.SpriteBatch spriteBatch)
        {
            (Item as IObject2D).Draw(spriteBatch);
        }

        /// <summary>
        /// Update the item.
        /// </summary>
        protected override void OnUpdate()
        {
            int i = 0;
            foreach (IPositionable2D obj in CommandList.Cast<IPositionable2D>())
            {
                obj.Position = GetItemOffset(i) + this.Position;
                ++i;
            }
        }
    }
}
